package com.ymt.bpm.web.rest.platform.profile;

import com.alibaba.fastjson.JSONObject;
import com.ymt.bpm.appboot.BpmpProperties;
import com.ymt.bpm.dao.MDao;
import com.ymt.bpm.dao.Mapper;
import com.ymt.bpm.engine.EngineConst;
import com.ymt.bpm.model.PNotifyOld;
import com.ymt.bpm.model.PTenant;
import com.ymt.bpm.model.PUser;
import com.ymt.bpm.model.bean.TenantForm;
import com.ymt.bpm.service.platform.profile.TenantService;
import com.ymt.bpm.util.AES;
import com.ymt.bpm.util.Const;
import com.ymt.bpm.util.DateUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

/**
 * Created by Johnny on 2017/1/30.
 */
@RestController
@EnableConfigurationProperties(BpmpProperties.class)
public class TenantResource {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private BpmpProperties bpmp;

    @Resource
    private MDao dao;

    @Autowired
    private TenantService ts;


    /**
     * register a tenant
     * @param form
     * @return
     */
    @RequestMapping(value="/openapi/v1/tenant/register", method= RequestMethod.POST)
    @Transactional(EngineConst.TRANSACTION_MANAGER)
    public JSONObject register(TenantForm form) {

        if (log.isDebugEnabled()) {
            log.debug("register: getName="+form.getName());
            log.debug("register: getDesc="+form.getDesc());
            log.debug("register: getClazz="+form.getClazz());
            log.debug("register: getEmail="+form.getEmail());
            log.debug("register: getSubscribe="+form.getSubscribe());
            log.debug("register: getContactPerson="+form.getContactPerson());
            log.debug("register: getPhone="+form.getPhone());
            log.debug("register: getMobile="+form.getMobile());
            log.debug("register: getRegisteredAt="+form.getRegisteredAt());
            log.debug("register: getProvince="+form.getProvince());
            log.debug("register: getCity="+form.getCity());
            log.debug("register: getStreet="+form.getStreet());
            log.debug("register: getPostCode="+form.getPostCode());
        }

        PTenant tenant = new PTenant();
        tenant.setName(form.getName());
        tenant.setDesc(form.getDesc());
        tenant.setEmail(form.getEmail());
        tenant.setClazz(form.getClazz());
        tenant.setSubscribe(form.getSubscribe());
        tenant.setCfg(ts.initCfgByClazz(form.getClazz()).toJSONString());
        switch (form.getClazz()) {
            case "0":
                tenant.setAcount(20);
                break;
            case "1":
                tenant.setAcount(100);
                break;
            case "2":
                tenant.setAcount(10000);
                break;
            default:
                log.warn("register default case is invalid.");
        }
        tenant.setOrgId("ORG-100");
        tenant.setStatus("0");
        tenant.setCreateTime(DateUtil.getGMTDate());
        tenant.setCreator(form.getContactPerson());

        JSONObject contact = new JSONObject();
        contact.put("contactPerson", form.getContactPerson());
        contact.put("phone", form.getPhone());
        contact.put("mobile", form.getMobile());
        contact.put("registeredAt", form.getRegisteredAt());
        contact.put("province", form.getProvince());
        contact.put("city", form.getCity());
        contact.put("street", form.getStreet());
        contact.put("postCode", form.getPostCode());
        tenant.setContact(contact.toJSONString());

        int rs = dao.insert("PTenantMapper", "insertSelective", tenant);
        JSONObject rtn = new JSONObject();
        rtn.put("result", rs);
        return rtn;
    }

    /**
     * get a tenant
     * @param request
     * @param id
     * @return
     */
    @RequestMapping(value="/api/v1/tenant/{id}", method= RequestMethod.GET)
    public PTenant get(HttpServletRequest request, @PathVariable("id")Integer id) {
        if (log.isDebugEnabled()) {
            log.debug("get id=" + id);
        }
        PTenant tenant = dao.selectOne("PTenantMapper", "selectByPrimaryKey", id);
        return tenant;
    }

    /**
     * get a tenant conf
     * @param request
     * @return
     */
    @RequestMapping(value="/api/v1/tenant/cfg", method= RequestMethod.GET)
    public JSONObject getCfg(HttpServletRequest request) {
        Map<String, String> userDetail = (Map<String, String>) SecurityContextHolder.getContext().getAuthentication().getDetails();
        String tenantId = userDetail.get(Const.TENANT_ID);
        if (tenantId==null) {
            tenantId = "0";
        }
        if (log.isDebugEnabled()) {
            log.debug("getCfg tenantId=" + tenantId);
        }
        return ts.getTenantConf(tenantId);
    }

    /**
     * get a tenant by invite code
     * @param request
     * @return
     */
    @RequestMapping(value="/openapi/v1/tenant/checkInviteCode",
            method= RequestMethod.GET,
            produces = "plain/text")
    public String checkInviteCode(HttpServletRequest request) {
        String value = request.getParameter("inviteCode");
        if (log.isDebugEnabled()) {
            log.debug("checkInviteCode inviteCode=" + value);
        }
        PTenant tenant = dao.selectOne("PTenantMapper", "selectByInviteCode", value);
        return tenant != null ? "true" : "false";
    }

    /**
     * check attr of a tenant
     * @return
     */
    @RequestMapping(value="/openapi/v1/tenant/checkAttr",
            produces = "plain/text")
    public String checkAttr(HttpServletRequest request) {
        String attrName = request.getParameterNames().nextElement();
        String value = request.getParameter(attrName);
        if (log.isDebugEnabled()) {
            log.debug("checkAttr attrName="+attrName);
            log.debug("checkAttr value="+value);
        }
        Map rs = dao.selectOne("PTenantMapper", "checkAttr"+StringUtils.capitalize(attrName), value);
        if (log.isDebugEnabled()) {
            log.debug("checkAttr rs="+rs);
        }
        for (Object key : rs.keySet()) {
            log.debug(key.getClass().getName());
        }
        long count = (long) rs.get("COUNT");
        return count>0 ? "false" : "true";
    }

    /**
     * update a tenant
     * @param request
     * @param form
     * @return
     */
    @RequestMapping(value="/api/v1/tenant/update", method= RequestMethod.POST)
    @Transactional(EngineConst.TRANSACTION_MANAGER)
    public JSONObject update(HttpServletRequest request, TenantForm form) {

        if (log.isDebugEnabled()) {
            log.debug("update: getTenantId="+form.getTenantId());
            log.debug("update: getName="+form.getName());
            log.debug("update: getDesc="+form.getDesc());
            log.debug("update: getClazz="+form.getClazz());
            log.debug("update: getEmail="+form.getEmail());
            log.debug("update: getSubscribe="+form.getSubscribe());
            log.debug("update: getContactPerson="+form.getContactPerson());
            log.debug("update: getPhone="+form.getPhone());
            log.debug("update: getMobile="+form.getMobile());
            log.debug("update: getRegisteredAt="+form.getRegisteredAt());
            log.debug("update: getProvince="+form.getProvince());
            log.debug("update: getCity="+form.getCity());
            log.debug("update: getStreet="+form.getStreet());
            log.debug("update: getPostCode="+form.getPostCode());
            log.debug(request.getParameter("name"));
        }

        PTenant tenant = new PTenant();
        tenant.setTenantId(form.getTenantId());
        tenant.setName(form.getName());
        tenant.setDesc(form.getDesc());
        tenant.setEmail(form.getEmail());
        tenant.setClazz(form.getClazz());
        tenant.setSubscribe(form.getSubscribe());
        //tenant.setCfg("{}");
        //tenant.setAcount(0);
        tenant.setOrgId("ORG-100");
        //tenant.setStatus("0");

        JSONObject contact = new JSONObject();
        contact.put("contactPerson", form.getContactPerson());
        contact.put("phone", form.getPhone());
        contact.put("mobile", form.getMobile());
        contact.put("registeredAt", form.getRegisteredAt());
        contact.put("province", form.getProvince());
        contact.put("city", form.getCity());
        contact.put("street", form.getStreet());
        contact.put("postCode", form.getPostCode());
        tenant.setContact(contact.toJSONString());

        int rs = dao.update("PTenantMapper", "updateByPrimaryKeySelective", tenant);
        JSONObject rtn = new JSONObject();
        rtn.put("result", rs);
        return rtn;
    }

    /**
     * update clazz of a tenant
     * @param id
     * @param clazz
     * @return
     */
    @RequestMapping(value="/api/v1/tenant/setClazz/{id}", method= RequestMethod.POST)
    @Transactional(EngineConst.TRANSACTION_MANAGER)
    public JSONObject setClazz(HttpServletRequest request,
                                @PathVariable("id")Integer id,
                               @RequestParam("clazz")String clazz) {
        PTenant tenant = dao.selectOne("PTenantMapper", "selectByPrimaryKey", id);
        tenant.setClazz(clazz);
        int rs = dao.update("PTenantMapper", "updateByPrimaryKeySelective", tenant);
        JSONObject rtn = new JSONObject();
        rtn.put("result", rs);
        return rtn;
    }

    /**
     * update status of a tenant
     * @param id
     * @param status
     * @return
     */
    @RequestMapping(value="/api/v1/tenant/state/{id}", method= RequestMethod.POST)
    @Transactional(EngineConst.TRANSACTION_MANAGER)
    public JSONObject state(@PathVariable("id")Integer id, @RequestParam("status")String status) {
        PTenant tenant = dao.selectOne("PTenantMapper", "selectByPrimaryKey", id);
        tenant.setStatus(status);
        int rs = dao.update("PTenantMapper", "updateByPrimaryKeySelective", tenant);
        JSONObject rtn = new JSONObject();
        rtn.put("result", rs);
        return rtn;
    }

    /**
     * generate inviteCode of a tenant
     * @param id
     * @return
     */
    @RequestMapping(value="/api/v1/tenant/approve/{id}", method= RequestMethod.GET)
    @Transactional(EngineConst.TRANSACTION_MANAGER)
    public JSONObject approve(@PathVariable("id")Integer id) {
        JSONObject rtn = new JSONObject();

        PTenant tenant = dao.selectOne("PTenantMapper", "selectByPrimaryKey", id);
        //邀请码
        String inviteCode = (tenant.getTenantId()+345)+ AES.random(6);
        tenant.setInviteCode(inviteCode);
        //状态值为1
        tenant.setStatus("1");
        //更新admin用户id到tenant
        String adminLoginName = "admin"+tenant.getTenantId();
        tenant.setAdmin(adminLoginName);
        int rs = dao.update("PTenantMapper", "updateByPrimaryKeySelective", tenant);

        //同时创建一个管理用户，以注册email为id
        String adminPassword = AES.random(6);
        PUser tenantAdmin = new PUser();
        tenantAdmin.setTenantId(tenant.getTenantId());
        tenantAdmin.setUserId(adminLoginName);
        tenantAdmin.setUserNumber(adminLoginName);
        tenantAdmin.setLoginName(adminLoginName);
        tenantAdmin.setRealName("超级管理员");
        tenantAdmin.setDisplayName("超级管理员("+adminLoginName+")");
        tenantAdmin.setPassword(DigestUtils.sha256Hex(adminPassword));
        tenantAdmin.setEmail(tenant.getEmail());
        JSONObject contact = JSONObject.parseObject(tenant.getContact());
        tenantAdmin.setMobile(contact.getString("mobile"));
        tenantAdmin.setUserType("0");
        tenantAdmin.setIsvalid("1");
        tenantAdmin.setStatus("10");
        tenantAdmin.setLang(Const.LANG_ZH);
        rs += dao.insert("PUserMapper", "insertSelective", tenantAdmin);

        //给该用户授权
        rs += dao.insert(Mapper.PResourceMapper, "initMenuForTenantAdmin", id);

        //发送审核通过通知邮件
        PNotifyOld notify = new PNotifyOld();
        notify.setTenantId(tenant.getTenantId());
        notify.setId(UUID.randomUUID().toString());
        notify.setTitle("【BPM云】您的企业号已通过审核");
        notify.setContent("我们荣幸的通知您，您在BPM云注册的的企业号已可以正常使用，额定帐号数量为"+tenant.getAcount()+"。<br/>"
                +"管理帐号为<b><font color=\"blue\">" +adminLoginName+"</font></b>，默认密码为"
                    +"<b><font color=\"blue\">"+adminPassword+"</font></b>，建议您首次登录后修改密码！<br/>"
                +"您还可以将邀请码（<b><font color=\"blue\">"+inviteCode+"</font></b>）发送给贵公司其他成员，令其自行注册！<br/>"
                +"祝您使用愉快！");
        notify.setReadUrl(bpmp.getSiteUrl());
        notify.setSender(bpmp.getServiceMailAddress());
        notify.setSenderName("【BPM云】服务");
        notify.setReceiver(adminLoginName);
        notify.setReceiverName(tenant.getCreator());
        Date now = DateUtil.getGMTDate();
        notify.setCreateTime(now);
        notify.setScheduleTime(now);
        notify.setType("0");
        notify.settType("C");
        notify.setStatus("0");
        notify.setDestination(tenant.getEmail());
        rs += dao.insert("PNotifyOldMapper", "insertSelective", notify);

        rtn.put("result", rs);
        return rtn;
    }

}
